import sys
import json
import os
import subprocess
from docx import Document
from docx.shared import Cm, Pt
from docx.oxml.ns import qn
from docx.oxml import OxmlElement
# 版权信息：归玉师人事处
from PySide6.QtWidgets import (QApplication, QMainWindow, QTextEdit, QVBoxLayout,
                               QWidget, QPushButton, QHBoxLayout, QLabel,
                               QFontComboBox, QSpinBox, QToolBar, QStatusBar,
                               QFileDialog, QMessageBox, QGroupBox, QFormLayout, QComboBox, QDoubleSpinBox, QSplitter)
from PySide6.QtGui import QFont, QAction, QClipboard, QIcon
from PySide6.QtCore import Qt
from qt_material import apply_stylesheet


class WordTableGeneratorUI(QMainWindow):
    def __init__(self):
        super().__init__()
        self.text_data = []
        # 预设单元格尺寸选项 (宽度, 高度) 单位：厘米
        self.cell_sizes = [
            (19.5, 9),
            (21, 9.6)
        ]
        self.selected_cell_size = self.cell_sizes[0]  # 默认选择第一个尺寸
        self.custom_size_enabled = False  # 标记是否启用自定义尺寸
        self.initUI()

    def initUI(self):
        self.setWindowTitle('席位牌制作')

        # 创建中央部件和布局
        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        
        # 创建分割器实现两栏布局
        splitter = QSplitter(Qt.Horizontal)
        splitter.setHandleWidth(5)
        splitter.setSizes([400, 800])  # 设置初始大小比例
        
        # 左侧控制面板
        left_panel = QWidget()
        left_layout = QVBoxLayout(left_panel)
        
        # 创建字体设置区域
        font_group = QGroupBox("字体设置")
        font_layout = QFormLayout()

        # 字体选择
        self.font_combo = QFontComboBox()
        self.font_combo.setCurrentFont(QFont("宋体"))
        self.font_combo.currentFontChanged.connect(self.on_font_changed)

        # 字号选择
        self.size_spin = QSpinBox()
        self.size_spin.setRange(8, 300)
        self.size_spin.setValue(150)  # 改为150号字体
        self.size_spin.valueChanged.connect(self.on_size_changed)

        font_layout.addRow(QLabel("字体:"), self.font_combo)
        font_layout.addRow(QLabel("字号:"), self.size_spin)
        font_group.setLayout(font_layout)

        # 创建单元格尺寸设置区域
        size_group = QGroupBox("单元格尺寸设置")
        size_layout = QFormLayout()

        # 预设尺寸选择
        self.size_preset_combo = QComboBox()
        for width, height in self.cell_sizes:
            self.size_preset_combo.addItem(f"{width}cm x {height}cm", (width, height))
        self.size_preset_combo.currentIndexChanged.connect(self.on_preset_changed)

        # 单元格宽度设置
        self.width_spin = QDoubleSpinBox()
        self.width_spin.setRange(5.0, 50.0)
        self.width_spin.setDecimals(1)
        self.width_spin.setSpecialValueText(" ")  # 空值显示为空格
        self.width_spin.setValue(0.0)  # 默认为空
        self.width_spin.valueChanged.connect(self.on_width_changed)

        # 单元格高度设置
        self.height_spin = QDoubleSpinBox()
        self.height_spin.setRange(3.0, 30.0)
        self.height_spin.setDecimals(1)
        self.height_spin.setSpecialValueText(" ")  # 空值显示为空格
        self.height_spin.setValue(0.0)  # 默认为空
        self.height_spin.valueChanged.connect(self.on_height_changed)

        size_layout.addRow(QLabel("预设尺寸:"), self.size_preset_combo)
        size_layout.addRow(QLabel("宽度(cm):"), self.width_spin)
        size_layout.addRow(QLabel("高度(cm):"), self.height_spin)
        size_group.setLayout(size_layout)

        # 添加控件到左侧布局
        left_layout.addWidget(font_group)
        left_layout.addWidget(size_group)
        left_layout.addStretch()

        # 右侧文本编辑区域
        right_panel = QWidget()
        right_layout = QVBoxLayout(right_panel)
        
        # 创建文本编辑区域
        text_group = QGroupBox("数据输入")
        text_layout = QVBoxLayout()
        self.text_edit = QTextEdit()
        self.text_edit.setFont(QFont('宋体', 12))
        self.text_edit.setPlaceholderText("在此输入数据，每行一条记录...")
        text_layout.addWidget(self.text_edit)
        text_group.setLayout(text_layout)
        
        right_layout.addWidget(text_group)
        
        # 创建按钮区域
        button_layout = QHBoxLayout()

        # 粘贴按钮
        paste_btn = QPushButton('粘贴数据')
        paste_btn.clicked.connect(self.paste_text)

        # 清空按钮
        clear_btn = QPushButton('清空')
        clear_btn.clicked.connect(self.clear_text)

        # 生成按钮
        generate_btn = QPushButton('生成Word文档')
        generate_btn.clicked.connect(self.generate_word)

        button_layout.addWidget(paste_btn)
        button_layout.addWidget(clear_btn)
        button_layout.addStretch()
        button_layout.addWidget(generate_btn)
        
        right_layout.addLayout(button_layout)

        # 将左右面板添加到分割器
        splitter.addWidget(left_panel)
        splitter.addWidget(right_panel)
        
        # 创建主布局并添加分割器
        main_layout = QVBoxLayout(central_widget)
        main_layout.addWidget(splitter)
        
        # 添加版权信息
        copyright_label = QLabel("版权所有© Copyright玉师人事处")
        copyright_label.setAlignment(Qt.AlignCenter)
        main_layout.addWidget(copyright_label)
        
        # 创建菜单栏
        self.create_menu()

        # 创建工具栏
        self.create_toolbar()

        # 创建状态栏
        self.status_bar = QStatusBar()
        self.setStatusBar(self.status_bar)
        self.status_bar.showMessage('就绪')

    def create_menu(self):
        menubar = self.menuBar()

        # 文件菜单
        file_menu = menubar.addMenu('文件')

        open_action = QAction('打开', self)
        open_action.setShortcut('Ctrl+O')
        open_action.triggered.connect(self.open_file)
        file_menu.addAction(open_action)

        save_action = QAction('保存', self)
        save_action.setShortcut('Ctrl+S')
        save_action.triggered.connect(self.save_file)
        file_menu.addAction(save_action)

        file_menu.addSeparator()

        exit_action = QAction('退出', self)
        exit_action.setShortcut('Ctrl+Q')
        exit_action.triggered.connect(self.close)
        file_menu.addAction(exit_action)

        # 编辑菜单
        edit_menu = menubar.addMenu('编辑')

        paste_action = QAction('粘贴', self)
        paste_action.setShortcut('Ctrl+V')
        paste_action.triggered.connect(self.paste_text)
        edit_menu.addAction(paste_action)

        clear_action = QAction('清空', self)
        clear_action.setShortcut('Ctrl+L')
        clear_action.triggered.connect(self.clear_text)
        edit_menu.addAction(clear_action)

    def create_toolbar(self):
        toolbar = QToolBar()
        self.addToolBar(toolbar)

        # 添加粘贴按钮到工具栏
        paste_action = QAction('粘贴', self)
        paste_action.triggered.connect(self.paste_text)
        toolbar.addAction(paste_action)

        # 添加清空按钮到工具栏
        clear_action = QAction('清空', self)
        clear_action.triggered.connect(self.clear_text)
        toolbar.addAction(clear_action)

    def on_font_changed(self, font):
        # 更新文本编辑器的字体
        current_font = self.text_edit.currentFont()
        current_font.setFamily(font.family())
        self.text_edit.setCurrentFont(current_font)

    def on_size_changed(self, size):
        # 更新文本编辑器的字号
        current_font = self.text_edit.currentFont()
        current_font.setPointSize(size)
        self.text_edit.setCurrentFont(current_font)

    def on_preset_changed(self, index):
        """当预设尺寸改变时更新spinbox和选定尺寸"""
        if index >= 0:  # 确保有效索引
            width, height = self.size_preset_combo.itemData(index)
            self.selected_cell_size = (width, height)
            # 更新自定义输入框但不触发valueChanged事件
            self.width_spin.blockSignals(True)
            self.height_spin.blockSignals(True)
            self.width_spin.setValue(width)
            self.height_spin.setValue(height)
            self.width_spin.blockSignals(False)
            self.height_spin.blockSignals(False)
            self.custom_size_enabled = False

    def on_width_changed(self, value):
        """当宽度改变时更新选定尺寸"""
        # 如果输入值大于0，则启用自定义尺寸
        if value > 0:
            self.custom_size_enabled = True
            self.selected_cell_size = (value, self.selected_cell_size[1])
        elif not self.height_spin.value() > 0:  # 如果宽高都为空，则使用默认预设
            self.custom_size_enabled = False
            # 重新选择默认预设
            self.size_preset_combo.blockSignals(True)
            self.size_preset_combo.setCurrentIndex(0)
            self.size_preset_combo.blockSignals(False)
            self.selected_cell_size = self.cell_sizes[0]

    def on_height_changed(self, value):
        """当高度改变时更新选定尺寸"""
        # 如果输入值大于0，则启用自定义尺寸
        if value > 0:
            self.custom_size_enabled = True
            self.selected_cell_size = (self.selected_cell_size[0], value)
        elif not self.width_spin.value() > 0:  # 如果宽高都为空，则使用默认预设
            self.custom_size_enabled = False
            # 重新选择默认预设
            self.size_preset_combo.blockSignals(True)
            self.size_preset_combo.setCurrentIndex(0)
            self.size_preset_combo.blockSignals(False)
            self.selected_cell_size = self.cell_sizes[0]

    def paste_text(self):
        # 粘贴文本
        clipboard = QApplication.clipboard()
        text = clipboard.text()
        self.text_edit.insertPlainText(text)
        self.status_bar.showMessage('已粘贴文本')

    def clear_text(self):
        # 清空文本
        self.text_edit.clear()
        self.status_bar.showMessage('已清空文本')

    def open_file(self):
        # 打开文件
        file_path, _ = QFileDialog.getOpenFileName(
            self, '打开文件', '', '文本文件 (*.txt);;JSON文件 (*.json);;所有文件 (*)')

        if file_path:
            try:
                with open(file_path, 'r', encoding='utf-8') as f:
                    if file_path.endswith('.json'):
                        data = json.load(f)
                        if isinstance(data, list):
                            text = '\n'.join([item.get('text', '') for item in data])
                        else:
                            text = str(data)
                    else:
                        text = f.read()
                    self.text_edit.setPlainText(text)
                self.status_bar.showMessage(f'已打开文件: {file_path}')
            except Exception as e:
                QMessageBox.critical(self, '错误', f'无法打开文件:\n{str(e)}')

    def save_file(self):
        # 保存文件
        file_path, _ = QFileDialog.getSaveFileName(
            self, '保存文件', '', '文本文件 (*.txt);;所有文件 (*)')

        if file_path:
            try:
                with open(file_path, 'w', encoding='utf-8') as f:
                    f.write(self.text_edit.toPlainText())
                self.status_bar.showMessage(f'已保存文件: {file_path}')
            except Exception as e:
                QMessageBox.critical(self, '错误', f'无法保存文件:\n{str(e)}')

    def set_cell_border(self, cell, style='dotted', color='auto', size='4'):
        """
        设置 Word 表格单元格的边框样式为虚线。
        """
        tc = cell._tc
        tcPr = tc.get_or_add_tcPr()
        tcBorders = OxmlElement('w:tcBorders')

        # 定义边框方向
        directions = ['top', 'left', 'bottom', 'right']
        for direction in directions:
            border = OxmlElement(f'w:{direction}')
            border.set(qn('w:val'), style)
            border.set(qn('w:color'), color)
            border.set(qn('w:sz'), size)
            tcBorders.append(border)

        tcPr.append(tcBorders)

    def generate_word(self):
        # 生成Word文档
        text_content = self.text_edit.toPlainText()
        if not text_content.strip():
            QMessageBox.warning(self, '警告', '请输入数据内容！')
            self.status_bar.showMessage('数据为空')
            return

        # 解析文本数据
        lines = text_content.strip().split('\n')
        data = [{"text": line.strip()} for line in lines if line.strip()]

        # 数据分组：每组3条数据，不足3条则填充空字符串
        groups = []
        for i in range(0, len(data), 3):
            group = data[i:i + 3]
            while len(group) < 3:
                group.append({"text": ""})
            groups.append(group)

        # 获取用户选择的字体和字号
        selected_font = self.font_combo.currentFont().family()
        selected_size = self.size_spin.value()

        try:
            # 创建 Word 文档
            doc = Document()

            # 设置页面为A4纸张大小
            section = doc.sections[0]
            section.page_height = Cm(29.7)  # A4纸张高度
            section.page_width = Cm(21)     # A4纸张宽度
            
            # 设置页面边距为0
            section.top_margin = Cm(0)
            section.bottom_margin = Cm(0)
            section.left_margin = Cm(0)
            section.right_margin = Cm(0)

            # 控制分页逻辑
            is_first_table = True

            for group in groups:
                if not is_first_table:
                    doc.add_page_break()
                else:
                    is_first_table = False

                # 设置表格列宽为用户选择的宽度，确保不超过页面宽度
                table_width = min(self.selected_cell_size[0], 21)  # 限制最大宽度为A4页面宽度
                
                # 添加表格
                table = doc.add_table(rows=3, cols=1)
                
                # 禁用表格自动调整功能
                table.autofit = False
                
                # 通过底层XML设置表格宽度
                from docx.oxml import OxmlElement
                from docx.oxml.ns import qn
                
                tbl = table._tbl
                tblPr = tbl.tblPr
                
                # 设置表格宽度
                tblW = OxmlElement('w:tblW')
                tblW.set(qn('w:w'), str(int(table_width * 567)))  # 转换为twips单位
                tblW.set(qn('w:type'), 'dxa')
                tblPr.append(tblW)
                
                # 设置表格布局为固定模式
                tblLayout = OxmlElement('w:tblLayout')
                tblLayout.set(qn('w:type'), 'fixed')
                tblPr.append(tblLayout)
                
                # 设置网格列宽度
                tblGrid = OxmlElement('w:tblGrid')
                gridCol = OxmlElement('w:gridCol')
                gridCol.set(qn('w:w'), str(int(table_width * 567)))  # 转换为twips单位
                tblGrid.append(gridCol)
                tbl.insert(0, tblGrid)
                
                # 设置列宽
                table.columns[0].width = Cm(table_width)
                
                # 设置行高
                for row in table.rows:
                    row.height = Cm(self.selected_cell_size[1])  # 使用用户选择的高度
                
                print(f'Table width: {table_width}')

                # 填充表格内容
                for idx in range(3):
                    cell = table.cell(idx, 0)
                    cell.text = ''  # 清除默认段落
                    paragraph = cell.add_paragraph()
                    # 设置段落居中对齐
                    paragraph.alignment = 1  # 1表示居中对齐
                    text = group[idx]['text']
                    run = paragraph.add_run(text)

                    # 设置字体样式
                    run.font.name = selected_font
                    r = run._element
                    rPr = r.get_or_add_rPr()
                    rFonts = OxmlElement('w:rFonts')
                    rFonts.set(qn('w:eastAsia'), selected_font)
                    rPr.append(rFonts)

                    run.font.size = Pt(selected_size)
                    run.bold = True

                # 为表格中的每个单元格设置虚线边框和居中对齐
                for row in table.rows:
                    for cell in row.cells:
                        self.set_cell_border(cell, style='dotted')
                        # 设置单元格垂直居中对齐
                        tc = cell._tc
                        tcPr = tc.get_or_add_tcPr()
                        vAlign = OxmlElement('w:vAlign')
                        vAlign.set(qn('w:val'), 'center')
                        tcPr.append(vAlign)

            # 保存文件对话框
            file_path, _ = QFileDialog.getSaveFileName(
                self, '保存Word文档', 'output.docx', 'Word文档 (*.docx)')

            if file_path:
                doc.save(file_path)
                self.status_bar.showMessage(f'Word文档已保存: {file_path}')
                QMessageBox.information(self, '成功', f'Word文档已成功保存到:\n{file_path}')
                
                # 保存完成后自动打开文件
                self.open_file_with_default_app(file_path)
            else:
                self.status_bar.showMessage('操作已取消')

        except Exception as e:
            QMessageBox.critical(self, '错误', f'生成Word文档时出错:\n{str(e)}')
            self.status_bar.showMessage('生成失败')

    def open_file_with_default_app(self, file_path):
        """使用默认应用程序打开文件"""
        try:
            if sys.platform.startswith('win'):
                os.startfile(file_path)
            elif sys.platform.startswith('darwin'):  # macOS
                subprocess.call(['open', file_path])
            else:  # linux
                subprocess.call(['xdg-open', file_path])
        except Exception as e:
            QMessageBox.warning(self, '警告', f'无法自动打开文件:\n{str(e)}')


def main():
    app = QApplication(sys.argv)
    window = WordTableGeneratorUI()
    apply_stylesheet(app, theme='dark_lightgreen.xml', invert_secondary=False)
    window.show()
    sys.exit(app.exec())


if __name__ == '__main__':
    main()